#include <mcs51/8051.h>
#include "frame_correct.h"
#define BTN_TRIGGER P4_3
#define BTN_ADD P3_2
#define BTN_SUB P3_3
#define BOARD_LED1 P3_0
#define BOARD_LED2 P3_1
#define LED_TRIGGER P0_0
#define CAMERA_TRIGGER P0_1
#define DISPLAY_CLK P3_1
#define DISPLAY_DIO P3_0
#define FRAME_BUT 10
#define FRAME_TOP 400

#define FOSC 11059200L
#define T1MS 65443

#define NOP __asm \
  nop \
  __endasm

#define anti_shake_begin(item) EA=0; \
  delay_ms(10); \
  if(BTN_##item==0) \
  {


#define anti_shake_end \
  }\
  EA=1; \


__sfr __at (0xe8) P4 ;
__sbit __at (0xe8) P4_0 ;
__sbit __at (0xe9) P4_1 ;
__sbit __at (0xea) P4_2 ;
__sbit __at (0xeb) P4_3 ;
__sbit __at (0xec) P4_4 ;
__sbit __at (0xed) P4_5 ;
__sbit __at (0xee) P4_6 ;

__sbit __at (0xE8^3) INT2 ;
__sbit __at (0xE8^2) INT3 ;

__sfr __at (0xC0) XICON;
__sbit __at (0xC0^7) PX3;
__sbit __at (0xC0^6) EX3;
__sbit __at (0xC0^5) IE3;
__sbit __at (0xC0^4) IT3;
__sbit __at (0xC0^3) PX2;
__sbit __at (0xC0^2) EX2;
__sbit __at (0xC0^1) IE2;
__sbit __at (0xC0^0) IT2;

static unsigned int frameRate=200;
static unsigned int interval=10;
static int ms_count=0;
static int triggerStatus=0;

union command
{
  struct 
  {
    unsigned char _1:1;
    unsigned char _2:1;
    unsigned char _3:1;
    unsigned char _4:1;
    unsigned char _5:1;
    unsigned char _6:1;
    unsigned char _7:1;
    unsigned char _8:1;
    unsigned char _9:1;
    unsigned char _10:1;
    unsigned char _11:1;
    unsigned char _12:1;
    unsigned char _13:1;
    unsigned char _14:1;
    unsigned char _15:1;
    unsigned char _16:1;
  } bit1_index;
  
  struct 
  {
    unsigned char L8:8; //低8位
    unsigned char H8:8; //高8位
  } bit8_index;

  unsigned int bit16;
};

union charBit
{
  struct 
  {
    unsigned char _1:1;
    unsigned char _2:1;
    unsigned char _3:1;
    unsigned char _4:1;
    unsigned char _5:1;
    unsigned char _6:1;
    unsigned char _7:1;
    unsigned char _8:1;
  } bit_index;
  unsigned char CharIndex;
};

union charBit fontData[]={
               //A B C D E F G DP
  [0].bit_index={1,1,1,1,1,1,0,0}, //0
  [1].bit_index={0,1,1,0,0,0,0,0}, //1
  [2].bit_index={1,1,0,1,1,0,1,0}, //2
  [3].bit_index={1,1,1,1,0,0,1,0}, //3
  [4].bit_index={0,1,1,0,0,1,1,0}, //4
  [5].bit_index={1,0,1,1,0,1,1,0}, //5
  [6].bit_index={1,0,1,1,1,1,1,0}, //6
  [7].bit_index={1,1,1,0,0,0,0,0}, //7
  [8].bit_index={1,1,1,1,1,1,1,0}, //8
  [9].bit_index={1,1,1,1,0,1,1,0}, //9
};

void delay_ms(unsigned int n)
{
	unsigned int i,j;
	for(i=0;i<n;i++)
		for(j=0;j<65;j++)
			;
}

inline void delay_halfms(unsigned int n)
{
	while(n--)
		;
}

void displayDataSend(unsigned int _CMD)
{
  union command CMD;
  CMD.bit16=_CMD;

  DISPLAY_DIO=0; 
  DISPLAY_CLK=0;
  DISPLAY_DIO=CMD.bit1_index._16;
  DISPLAY_CLK=1;
  NOP;

  DISPLAY_CLK=0;
  DISPLAY_DIO=CMD.bit1_index._15;
  DISPLAY_CLK=1;
  NOP;

  DISPLAY_CLK=0;
  DISPLAY_DIO=CMD.bit1_index._14;
  DISPLAY_CLK=1;
  NOP;

  DISPLAY_CLK=0;
  DISPLAY_DIO=CMD.bit1_index._13;
  DISPLAY_CLK=1;
  NOP;


  DISPLAY_CLK=0;
  DISPLAY_DIO=CMD.bit1_index._12;
  DISPLAY_CLK=1;
  NOP;


  DISPLAY_CLK=0;
  DISPLAY_DIO=CMD.bit1_index._11;
  DISPLAY_CLK=1;
  NOP;

  DISPLAY_CLK=0;
  DISPLAY_DIO=CMD.bit1_index._10;
  DISPLAY_CLK=1;
  NOP;

  DISPLAY_CLK=0;
  DISPLAY_DIO=CMD.bit1_index._9;
  DISPLAY_CLK=1;
  NOP;

  //ACK
  DISPLAY_CLK=0;
  DISPLAY_DIO=0;
  NOP;
  DISPLAY_CLK=1;
  NOP;

  DISPLAY_CLK=0;
  DISPLAY_DIO=CMD.bit1_index._8;
  DISPLAY_CLK=1;
  NOP;

  DISPLAY_CLK=0;
  DISPLAY_DIO=CMD.bit1_index._7;
  DISPLAY_CLK=1;
  NOP;

  DISPLAY_CLK=0;
  DISPLAY_DIO=CMD.bit1_index._6;
  DISPLAY_CLK=1;
  NOP;

  DISPLAY_CLK=0;
  DISPLAY_DIO=CMD.bit1_index._5;
  DISPLAY_CLK=1;
  NOP;

  DISPLAY_CLK=0;
  DISPLAY_DIO=CMD.bit1_index._4;
  DISPLAY_CLK=1;
  NOP;

  DISPLAY_CLK=0;
  DISPLAY_DIO=CMD.bit1_index._3;
  DISPLAY_CLK=1;
  NOP;


  DISPLAY_CLK=0;
  DISPLAY_DIO=CMD.bit1_index._2;
  DISPLAY_CLK=1;
  NOP;

  DISPLAY_CLK=0;
  DISPLAY_DIO=CMD.bit1_index._1;
  DISPLAY_CLK=1;
  NOP;

  //ACK
  DISPLAY_CLK=0;
  DISPLAY_DIO=0;
  NOP;
  DISPLAY_CLK=1;
  NOP;
  //END
  DISPLAY_CLK=0;
  NOP;
  DISPLAY_CLK=1;
  DISPLAY_DIO=1;
}

void displayNumber(int number)
{
  int singleNum;
  union command newCMD;
  char dispMEM=0x6E;
  for(int i=1;i<=4;i++)
  {
    singleNum=number%10;
    number/=10;
    newCMD.bit8_index.H8=dispMEM;
    newCMD.bit8_index.L8=fontData[singleNum].CharIndex;
    displayDataSend(newCMD.bit16);
    dispMEM-=2;
    if(number==0)
    {
	    while(i<4)
	    {
		    i++;
    		    newCMD.bit8_index.H8=dispMEM;
    		    newCMD.bit8_index.L8=0x00;
    		    displayDataSend(newCMD.bit16);
    		    dispMEM-=2;
	    }
	    break;
    }
  }
  displayDataSend(0x4801);
}


void ext_intADD(void) __interrupt (0) __using (2)
{
  anti_shake_begin(ADD) 
  if(frameRate<FRAME_TOP)
  {
    frameRate+=interval;
    displayNumber(frameRate);
  }
  anti_shake_end
}

void ext_intSUB(void) __interrupt (2)
{
  anti_shake_begin(SUB)
  if(frameRate>FRAME_BUT)
  {
    frameRate-=interval;
    displayNumber(frameRate);
  }
  anti_shake_end
}

void ext_intTRIGGER(void) __interrupt (6) __using (2)
{
  anti_shake_begin(TRIGGER)
  triggerStatus=!triggerStatus;
  //TR0=triggerStatus;
  LED_TRIGGER=!triggerStatus;
  anti_shake_end
}

//
void timer0_int1(void) __interrupt (1) __using(1)
{
		NOP;
  //TL0=0xA3;
  //TH0=0xFF;
  
  if(ms_count <= 0)
  {
    ms_count=150;
    CAMERA_TRIGGER=0;
    NOP;
    NOP;
    NOP;
    NOP;
    NOP;
    CAMERA_TRIGGER=1;
  }
  ms_count--;
}

void main(void)
{
	LED_TRIGGER=1;
	CAMERA_TRIGGER=0;

  	//btn add
  	IT0=1;
  	EX0=1;
  	//btn sub
  	IT1=1;
  	EX1=1;
	//btn trigger
	IT2=1;
	EX2=1;
	//timer
	TMOD=0x02; //8位自动重装
	TL0=0xF6;
	TH0=0xF6;
	ET0=0;
	TR0=0;

	EA=1;

	displayNumber(frameRate);

	while(1)
	{
		if(triggerStatus!=0)
		{
			  CAMERA_TRIGGER=!CAMERA_TRIGGER;
			  delay_halfms(frame_correct[frameRate/10-1]);
		}
	}
}
